/*
 *   AS IS License
 * ==Naive Coders==
 */
package org.naive.metawatch.converter.cap;

import java.text.ParseException;
import org.naive.metawatch.converter.parser.FieldSize;
import org.naive.metawatch.converter.parser.ParsedFixedIntArray;
import org.naive.metawatch.converter.parser.ParsedFixedSizeArray;
import org.naive.metawatch.converter.parser.ParsedIntArray;
import org.naive.metawatch.converter.parser.cap.CapParseContext;
import org.naive.metawatch.converter.parser.cap.CapParseable;

/**
 *
 * @author gbu.000
 */
public class CapClassOrInterfaceInfo extends CapParseable {
    
    private byte flagsAndCount;
    // interface 
    public CapClassRef[] super_interfaces;
    public byte[] remoteInterfaceName;
    // class stuff
    public CapClassRef superClass;
    public byte declared_instance_size;
    public byte first_reference_token;
    public byte reference_count;
    public byte public_method_table_base;
    public byte public_method_table_count;
    public byte package_method_table_base;
    public byte package_method_table_count;
    public short[] public_virtual_method_table;
    public short[] package_virtual_method_table;
    public CapImplementedInterfaceInfo[] interfaces;
  //  public CapRemoteInterfaceInfo classRemoteInterface;
    
    public boolean isInterface() {
        return (flagsAndCount & (0x8 << 4)) != 0;
    }
    
    public boolean isShareable() {
        return (flagsAndCount & (0x4 << 4)) != 0;
    }
    
    public boolean isRemote() {
        return (flagsAndCount & (0x2 << 4)) != 0;
    }
    
    public byte getInterfaceCount() {
        return (byte) (flagsAndCount & 0xF);
    }
    
    @Override
    public void parse(CapParseContext px) throws ParseException {
        flagsAndCount = px.readByte();
        try {
            if (isInterface()) {
                super_interfaces = (CapClassRef[]) ParsedFixedSizeArray.FieldParser.parse(px,
                        getInterfaceCount(), CapClassRef.class, CapClassRef.class);
                if (isRemote()) {
                    remoteInterfaceName = (byte[]) ParsedIntArray.FieldParser.parse(px, FieldSize.BYTE,
                            FieldSize.BYTE, byte.class);
                }
            } else {
                parseClass(px);
            }
        } catch (Exception e) {
            ParseException exx = new ParseException("", px.getOffset());
            exx.initCause(e);
            throw exx;
        }
    }
    
    private void parseClass(CapParseContext px) throws ParseException, Exception {
        superClass = new CapClassRef();
        superClass.parse(px);
        
        declared_instance_size = px.readByte();
        first_reference_token = px.readByte();
        reference_count = px.readByte();
        public_method_table_base = px.readByte();
        public_method_table_count = px.readByte();
        package_method_table_base = px.readByte();
        package_method_table_count = px.readByte();
        public_virtual_method_table = (short[]) ParsedFixedIntArray.FieldParser.parse(px,
                public_method_table_count, FieldSize.SHORT, short.class);
        package_virtual_method_table = (short[]) ParsedFixedIntArray.FieldParser.parse(px,
                package_method_table_count, FieldSize.SHORT, short.class);
        interfaces = (CapImplementedInterfaceInfo[]) ParsedFixedSizeArray.FieldParser.parse(px,
                getInterfaceCount(), CapImplementedInterfaceInfo.class, CapImplementedInterfaceInfo.class);
        
//        classRemoteInterface = new CapRemoteInterfaceInfo();
//        classRemoteInterface.parse(px);
    }
}
